/**
 * @name $
 */
(function($) {
	/**
 	 * @name KOR.rangeSlider
	 */
	KOR.rangeSlider = function(selector, mixin) {
		return KOR.RangeSlider.getInstanceOf(selector, mixin);
	};

	KOR.RangeSlider = KOR.createClass(KOR.LazyObject, {
		NAME: 'rangeSlider',

		grooveClass: 'groove',
		handleClass: 'handle',
		focusedClass: 'focused',
		horizontal: true,
		hideOnLeave: false,
		latency: 0.1,
		low: 0,
        high: 100,
		value: 0,
		integral: true,

		initAction: function(node, ev, data) {
			return new RangeSlider(node, {
				grooveClass: this.grooveClass,
				handleClass: this.handleClass,
				focusedClass: this.focusedClass,
				latency: this.latency,
				horizontal: this.horizontal,
				hideOnLeave: this.hideOnLeave,
				low: this.low,
				high: this.high,
				value: this.value,
				integral: this.integral,
				name: this.NAME
			})
		}
	});

	var RangeSlider = KOR.createClass(KOR.eventMixin, {
		init: function(node, mixin){
			this.node = $(node);
			$.extend(this, mixin);
			this.renderDomStructure();
			this.registerEvents();
			this.mouseenterHandler();
			if (this.high - this.low <= 1) {
				this.hide();
			}
            this.node.trigger('{{}}:initialize'.uInject(this.name));
		},

		renderDomStructure: function(){
			this.node.empty();
            this._groove = $('<div>').addClass(this.grooveClass);
            this._handle = $('<div>').addClass(this.handleClass);
            this._groove.append(this._handle);
            this.node.append(this._groove);
		},

		registerEvents: function(){
			var root = $.browser.msie?document:window;
			this.node.bind('mouseenter', $.proxy(this,'mouseenterHandler'));
            this.node.bind('mouseleave', $.proxy(this,'thismouseleaveHandler'));
            this.node.delegate('.'+this.handleClass, 'mousedown', $.proxy(this,'mousedownHandler'));
            $(root).delegate('html', 'mouseup', $.proxy(this,'mouseupHandler'));
            $(root).delegate('html', 'mousemove', $.proxy(this,'mousemoveHandler'));
            $(root).delegate('html', 'mouseleave', $.proxy(this,'windowmouseleaveHandler'));
		},

		mouseenterHandler: function () {
            this._hideOnRelease = false;
			if (this.high - this.low > 1) {
				this.show();
			}
        },

		thismouseleaveHandler: function () {
            if (!this.hideOnLeave) return;
            if (this._anchor) {
                this._hideOnRelease=true;
                return;
            }
            this.hide();
        },

		mousedownHandler: function (ev) {
            this._anchor = this._position = {left: ev.pageX, top: ev.pageY };
            this.node.addClass(this.focusedClass);
            this.interval();
            return false;
        },

		mouseupHandler: function (ev) {
            if (this._hideOnRelease) {
                this.hide();
            }
            this.node.removeClass(this.focusedClass);
            this._anchor = this._position = null;
        },

		mousemoveHandler: function (ev) {
            if (!this._anchor) return;
            this._position = {left: ev.pageX, top: ev.pageY };
        },

		windowmouseleaveHandler: function (ev) {
            if (ev.toElement) return;
            this.mouseupHandler.apply(this, arguments);
        },

		interval: function () {
            var inst = this;
            if (!this._anchor) return;
            this.tick();
            setTimeout(function () { inst.interval(); }, this.latency*1000);
        },

        tick: function () {
            var posAttr = this.horizontal?'left':'top',
                dimAttr = this.horizontal?'width':'height',
                handleWidth = this._handle[dimAttr](),
                handleThrow = this._groove[dimAttr]()-handleWidth,
                grvOfs = this._groove.offset(),
                pos = Math.max(0,Math.min(this._position[posAttr]-grvOfs[posAttr]-handleWidth/2, handleThrow)),
                value = pos/handleThrow*(this.high-this.low)+this.low;
            if (this.integral) value = Math.round(value);
            this.change(value);
        },

        show: function () {
            this.node.stop().animate({opacity: 1});
            return this;
        },
        /**
         * Overloading the .hide() method
         **/
        hide: function () {
            this.node.stop().animate({opacity: 0});
            return this;
        },

		configure: function (mixin) {
            this.init(this.node, mixin);
            return this;
        },
		
		moveSlider: function (value, force) {
			if (this.value == value && !force) return false;
            this.value = value;
            var posAttr = this.horizontal?'left':'top',
                dimAttr = this.horizontal?'width':'height',
                handleWidth = this._handle[dimAttr](),
                handleThrow = this._groove[dimAttr]()-handleWidth,
                pos = Math.round((value-this.low)*handleThrow/(this.high-this.low));
            this._handle.css(posAttr, pos);
			return true;
		},

		change: function (value, force) {
            if (this.moveSlider(value, force)) {
				this.node.trigger('{{}}:change'.uInject(this.name), this.value);
				return true;
			}
			return false;
        }

	});

})(jQuery);
